package com.linksfield.topup.service.impl;

import com.alibaba.fastjson.JSON;
import com.linksfield.topup.config.dto.CalculateResultParamVo;
import com.linksfield.topup.config.dto.PageAndSort;
import com.linksfield.topup.config.dto.ResultDataDto;
import com.linksfield.topup.config.dto.StringOutputConstant;
import com.linksfield.topup.entity.common.PartnerServicePlan;
import com.linksfield.topup.entity.common.ServicePlanOrderRecord;
import com.linksfield.topup.entity.common.ServicePlanOrderRefund;
import com.linksfield.topup.entity.interfaces.ordermanage.details.request.RequestOrderDetails;
import com.linksfield.topup.entity.interfaces.ordermanage.details.response.*;
import com.linksfield.topup.entity.interfaces.ordermanage.orderexport.request.RequestOrderExport;
import com.linksfield.topup.entity.interfaces.ordermanage.search.request.RequestOrderSearch;
import com.linksfield.topup.entity.interfaces.ordermanage.search.response.ResponseOrderCalculateCount;
import com.linksfield.topup.entity.interfaces.ordermanage.search.response.ResponseOrderSearch;
import com.linksfield.topup.entity.interfaces.ordermanage.search.response.ResponseServicePlanOrder;
import com.linksfield.topup.entity.servserapi.querydeviceorder.response.DevicePackageOrder;
import com.linksfield.topup.entity.servserapi.querydeviceorder.response.ResponseQueryDeviceOrder;
import com.linksfield.topup.entity.servserapi.queryorder.response.ResponseordersQueryNew;
import com.linksfield.topup.entity.servserapi.queryorder.response.ResponseordersQueryTradeData;
import com.linksfield.topup.mapper.OrderMapper;
import com.linksfield.topup.mapper.PartnerInfoMapper;
import com.linksfield.topup.mapper.ServicePlanMapper;
import com.linksfield.topup.service.OrderService;
import com.linksfield.topup.utils.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service("orderService")
@Transactional(rollbackFor = Exception.class)

/**
 * 订单管理业务逻辑处理实现类
 *
 * @author: lm
 * @date: 2019-12-09 15:40
 */
@Slf4j
public class OrderServiceImpl implements OrderService {
    @Autowired
    CommonUtilsServiceImpl utilsService;
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private PartnerInfoMapper partnerMapper;
    @Resource
    private ServicePlanMapper planMapper;
    /**
     * 定义了一个时间格式：yyyy-MM-dd HH:mm:ss
     */
    SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /***
     *  订单管理：搜索:
     *  点击“订单管理”默认请求此接口，只不过所有默认条件为空
     * @param request
     * @param token
     * @return
     */
    @Override
    public ResultDataDto search(RequestOrderSearch request, String token) {

        if (StringUtils.isBlank(token)) {
            return ResultDataDto.addOperationFailure(StringOutputConstant.CODE_TOKEN_EMPTY);
        }
        //1,先去公共服务类验证token
        String results = utilsService.checkToken(token);

        if (StringUtils.isBlank(results) || !StringOutputConstant.CODE_SUCCESS.equals(results)) {
            // 验证token出现问题，直接返回
            return ResultDataDto.addOperationFailure(results);
        }
        //确认安全，开始验证参数
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getLang()) || StringUtils.isBlank(request.getVersion()) ||
                null == request.getPartnerCode() || null == request.getCondition() || null == request.getStartDate() || null == request.getEndDate() ||
                null == request.getPackageStatus() || null == request.getPayStatus() || null == request.getRp() || null == request.getCurrentPage()) {
            // 上报的参数有误
            return ResultDataDto.addOperationFailure(StringOutputConstant.CODE_PARAM_ERROR);
        }
        /*先去把总数拿回来*/
        long rowCount = orderMapper.searchPageCount(request);
        /*分页内容：包含页码，每页显示行数，总条数*/
        PageAndSort pageHelper = utilsService.buildUpPageAndSort(request.getRp(), request.getCurrentPage(), rowCount);

        /*计算出所有支付成功的订单：订单总数个数，未启用个数，正在使用个数，已取消个数*/
        List<CalculateResultParamVo> countList = orderMapper.calculatePackageStatus(request);
        Map<String, Integer> map = new HashMap<>();
        for (CalculateResultParamVo vo : countList) {
            map.put(vo.getPackageStatus(), vo.getCounts());
        }
        /*除了：未启用，正在使用，已取消这几种状态之外的所有状态*/
        Integer packageStatus0 = 0;
        /*未启用状态*/
        Integer packageStatus1 = 0;
        /*正在使用状态*/
        Integer packageStatus2 = 0;
        /*已取消状态*/
        Integer packageStatus3 = 0;
        for (String key : map.keySet()) {
            if ("0".equals(key)) {
                packageStatus0 = map.get(key);
            }
            if ("1".equals(key)) {
                packageStatus1 = map.get(key);
            }
            if ("2".equals(key)) {
                packageStatus2 = map.get(key);
            }
            if ("3".equals(key)) {
                packageStatus3 = map.get(key);
            }
        }
        /*计算支付结果到达服务器的数据：已支付个数，已退款个数*/
        List<CalculateResultParamVo> countList2 = orderMapper.calculatePayStatus(request);

        Map<String, Integer> map2 = new HashMap<>();
        for (CalculateResultParamVo vo : countList2) {
            map2.put(vo.getPayStatus(), vo.getCounts());
        }
        /*已支付*/
        Integer payStatus1 = 0;
        /*已退款*/
        Integer payStatus2 = 0;
        for (String key : map2.keySet()) {
            if ("1".equals(key)) {
                payStatus1 = map2.get(key);
            }
            if ("2".equals(key)) {
                payStatus2 = map2.get(key);
            }
        }

        /*计算：单次购买个数，自动订阅个数*/
        List<CalculateResultParamVo> countList3 = orderMapper.calculatePayMode(request);
        Map<String, Integer> map3 = new HashMap<>();
        for (CalculateResultParamVo vo : countList3) {
            map2.put(vo.getPayMode(), vo.getCounts());
        }
        /*单次购买*/
        Integer payMode0 = 0;
        /*自动订阅*/
        Integer payMode1 = 0;
        for (String key : map3.keySet()) {
            if ("0".equals(key)) {
                payMode0 = map3.get(key);
            }
            if ("1".equals(key)) {
                payMode1 = map3.get(key);
            }
        }

        /*计算的内容前端没有使用但是也需要返回*/
        ResponseOrderCalculateCount count = new ResponseOrderCalculateCount();
        /*交易类型相加绝对可以做总数，只会有这两个值不会又有别的*/
        count.setOrderTotalCount(payMode0 + payMode1);
        count.setNotBeenUsedCount(packageStatus1);
        count.setInUseCount(packageStatus2);
        count.setCancelledCount(packageStatus3);
        count.setSuccessPayCount(payStatus1);
        count.setRefundCount(payStatus2);
        count.setSinglePayCount(payMode0);
        count.setSubscriptionCount(payMode1);

        //4,拿着请求主体和分页的数据去分页查询订单列表 (渠道套餐服务计划订单列表)
        List<ServicePlanOrderRecord> orderList = orderMapper.search(request, pageHelper);

        List<ResponseServicePlanOrder> responseList = new ArrayList<>();

        for (ServicePlanOrderRecord o : orderList) {

            ResponseServicePlanOrder order = new ResponseServicePlanOrder();
            order.setPartnerCode(o.getPartnerCode());
            order.setPartnerName(o.getPartnerName());
            order.setPayId(o.getPayId());
            order.setOrderNo(o.getOrderNo());
            order.setDeviceCode(o.getDeviceCode());
            order.setServicePlanShowName(o.getServicePlanShowName());
            order.setOrderPeriod(utilsService.setOrderPeriod(o.getPackageType(), o.getOrderPeriod()));
            order.setPayAmount(o.getPayUnit());
            order.setPayCurrency(o.getPayCurrency());
            order.setPackageStatus(utilsService.setPackageStatus(o.getPackageStatus()));
            order.setPayStatus(utilsService.setPayStatus(o.getPayStatus()));
            order.setPayMode(utilsService.setPayMode(o.getPayMode()));
            try {
                order.setCreateDate(o.getPayResultDate());
                if (StringUtils.isNotBlank(o.getOrderStartDate())) {
                    SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    df.setLenient(false);
                    if (StringUtils.isNotBlank(checkDateFormat(o.getOrderStartDate(), df))) {
                        order.setOrderTime(new SimpleDateFormat("yyyy-MM-dd").format(df.parse(o.getOrderStartDate())));
                    } else {
                        //如果这种情况返回为空，说明可能是另外一种形式
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
                        sdf.setLenient(false);
                        if (StringUtils.isNotBlank(checkDateFormat(o.getOrderStartDate(), sdf))) {
                            order.setOrderTime(new SimpleDateFormat("yyyy-MM-dd").format(sdf.parse(o.getOrderStartDate())));
                        } else {
                            order.setOrderTime("-");
                        }
                    }
                } else {
                    order.setOrderTime("-");
                }
            } catch (Exception e) {
                log.debug("时间转换异常！" + e);
                order.setOrderTime("-");
            }

            responseList.add(order);
        }
        //返回
        ResponseOrderSearch response = new ResponseOrderSearch();
        response.setCalculateCount(count);
        response.setOrderList(responseList);
        log.info("订单管理：搜索:" + JSON.toJSONString(response));
        //成功：给前端统一返回
        return ResultDataDto.addOperationSuccess().setData(response).setPageAndSort(pageHelper);
    }

    /***
     * 订单管理：订单详情
     * @param request
     * @param token
     * @return
     */
    @Override
    public ResultDataDto orderDetails(RequestOrderDetails request, String token) {

        if (StringUtils.isBlank(token)) {
            return ResultDataDto.addOperationFailure(StringOutputConstant.CODE_TOKEN_EMPTY);
        }
        //1,先去公共服务类验证token
        String results = utilsService.checkToken(token);

        if (StringUtils.isBlank(results) || !StringOutputConstant.CODE_SUCCESS.equals(results)) {
            // 验证token出现问题，直接返回
            return ResultDataDto.addOperationFailure(results);
        }
        //确认安全，开始验证参数
        if (StringUtils.isBlank(request.getTradeType()) || StringUtils.isBlank(request.getLang()) || StringUtils.isBlank(request.getVersion()) || StringUtils.isBlank(request.getPartnerCode()) ||
                StringUtils.isBlank(request.getPayId()) || StringUtils.isBlank(request.getOrderNo()) || StringUtils.isBlank(request.getDeviceCode())) {
            // 上报的参数有误
            return ResultDataDto.addOperationFailure(StringOutputConstant.CODE_PARAM_ERROR);
        }

        //根据上报的信息：partnerCode和payId 和deviceCode查询订单对应的信息
        List<ServicePlanOrderRecord> orderList = orderMapper.orderDetails(request.getPartnerCode(), request.getPayId(), request.getDeviceCode(), request.getOrderNo());
        ResponseOrderTrackingInfo trackingInfo = null;
        ResponseOrderProductInfo productInfo = null;
        ResponseOrderUserInfo userInfo = null;
        ResponseOrderOrderInfo orderInfo = null;
        String partnerCode = "";
        String orderId = "";
        String deviceCode = "";
        for (ServicePlanOrderRecord o : orderList) {
            partnerCode = o.getPartnerCode();
            orderId = o.getOrderId();
            deviceCode = o.getDeviceCode();
            //C:产品信息
            List<PartnerServicePlan> planList = planMapper.editInfo(o.getPartnerCode(), o.getServicePlanCode());
            productInfo = new ResponseOrderProductInfo();
            for (PartnerServicePlan p : planList) {
                productInfo.setServicePlanShowName(p.getServicePlanShowName());
                productInfo.setServicePlanCode(p.getServicePlanCode());
                productInfo.setPackageFlow(p.getPackageFlow() + "M");
                productInfo.setPackageType(utilsService.setPackageTypeShow(p.getPackageType()));
                productInfo.setOrderPeriod(utilsService.setOrderPeriod(p.getPackageType(), o.getOrderPeriod()));
                productInfo.setAvailableRange(utilsService.setAvailableRange(p.getPackageType(), p.getMinOrderPeriod(), p.getMaxOrderPeriod()));
                productInfo.setContinentName(utilsService.duplicateRemoval(p.getContinentName()));
                productInfo.setCoverCountrys(utilsService.duplicateRemoval(p.getCoverCountrys()));
                /*productInfo.setPayAmount(utilsService.setPayAmount(o.getPayCurrency(), o.getPayAmount()));*/
                productInfo.setPayAmount(utilsService.setPayAmount(o.getPayCurrency(), o.getPayUnit()));
            }
            //D:用户信息
            userInfo = new ResponseOrderUserInfo();
            userInfo.setDeviceCode(o.getDeviceCode());

            //E:订单信息
            orderInfo = new ResponseOrderOrderInfo();
            orderInfo.setOrderId(o.getOrderId());
            orderInfo.setPayId(o.getPayId());
            try {
                orderInfo.setCreateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(s.parse(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(o.getCreateDate()))));
                orderInfo.setPayDate(new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(o.getPayResultDate())));
            } catch (Exception e) {
                log.debug("时间转换发生了异常！" + e);
                orderInfo.setCreateDate("-");
                orderInfo.setPayDate("-");
            }
            orderInfo.setPayType(utilsService.setPayType(o.getPayType()));
            orderInfo.setTransactionId(o.getTransactionId());
            orderInfo.setPayAccount(utilsService.setPayAccount(o.getPayAccount()));
            orderInfo.setPartnerName(o.getPartnerName());
        }

        //A:现在去查询卡片的状态：去北京查询对应orderId
        String secret = partnerMapper.getSecret(partnerCode);
        if (StringUtils.isNotBlank(partnerCode) && StringUtils.isNotBlank(secret) && StringUtils.isNotBlank(orderId) && StringUtils.isNotBlank(deviceCode)) {
            /*去数据库匹配当前企业是不是已经从2.0迁到3.0了，因为2.0和3.0所走的路都不一样*/
            /*这个企业已经迁移到了3.0*/
            ResponseQueryDeviceOrder response = utilsService.queryDeviceOrder(deviceCode, orderId, "", "", partnerCode, secret);

            if (null != response && StringOutputConstant.CODE_SUCCESS_ZERO.equals(response.getCode()) && null != response.getData() && null != response.getData().getPackageOrder() && !response.getData().getPackageOrder().isEmpty()) {

                for (DevicePackageOrder tr : response.getData().getPackageOrder()) {

                    if (StringUtils.isNotBlank(tr.getOrderId()) && StringUtils.isNotBlank(tr.getActiveDate())) {

                        trackingInfo = new ResponseOrderTrackingInfo();
                        try {
                            trackingInfo.setOrderStartDate(new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyyMMdd").parse(tr.getActiveDate())));
                            trackingInfo.setOrderExpireDate(new SimpleDateFormat("yyyy-MM-dd").format(new SimpleDateFormat("yyyyMMdd").parse(tr.getExpireDate())));
                        } catch (Exception e) {
                            log.debug("时间转换发生了异常！");
                        }

                        if (StringUtils.isNotBlank(tr.getFlow()) && StringUtils.isNotBlank(tr.getUsedFlow())) {
                            try {
                                //算成订单总的流量
                                float totalFlow = Float.valueOf(tr.getOrderPeriod()) * Float.valueOf(tr.getFlow());
                                String flow = new DecimalFormat("##").format(totalFlow);

                                //将所有已经使用的流量换成M为单位
                                float usedFlow = Float.valueOf(tr.getUsedFlow()) / 1024;
                                String used = new DecimalFormat("##").format(usedFlow);
                                /*剩余流量=总的流量-已经使用的流量,按照'M'显示：String surplusFlow = String.valueOf(Integer.valueOf(flow) - Integer.valueOf(used));trackingInfo.setOrderUsedFlow(used + "M");*/

                                /*剩余流量=总的流量-已经使用的流量，按照'KB'显示*/
                                String surplusFlow = String.format("%.2f", (Double.parseDouble(tr.getFlow()) - Double.parseDouble(tr.getUsedFlow()) / 1024));

                                trackingInfo.setOrderUsedFlow(tr.getUsedFlow() + "KB");
                                trackingInfo.setOrderSurplusFlow(surplusFlow + "M");

                            } catch (Exception e) {
                                log.info("计算剩余流量出现异常");
                            }
                        } else {
                            trackingInfo.setOrderUsedFlow("-");
                            trackingInfo.setOrderSurplusFlow("-");
                        }
                    }
                }
            }
        }
        //返回内容准备
        ResponseOrderDetails response = new ResponseOrderDetails();
        response.setProductInfo(productInfo);
        response.setUserInfo(userInfo);
        response.setTrackingInfo(trackingInfo);
        response.setOrderInfo(orderInfo);

        log.info("订单详情:" + JSON.toJSONString(response));
        //成功：给前端统一返回
        return ResultDataDto.addOperationSuccess().setData(response);
    }


    /***
     *订单管理：导出订单
     * @param request
     * @param token
     * @return
     */
    @Override
    public ResultDataDto orderExport(RequestOrderExport request, String token, HttpServletResponse response) {

        if (StringUtils.isBlank(token)) {
            return ResultDataDto.addOperationFailure(StringOutputConstant.CODE_TOKEN_EMPTY);
        }
        //1,先去公共服务类验证token
        String results = utilsService.checkToken(token);

        if (StringUtils.isBlank(results) || !StringOutputConstant.CODE_SUCCESS.equals(results)) {
            // 验证token出现问题，直接返回
            return ResultDataDto.addOperationFailure(results);
        }
        //确认安全，开始验证参数
        if (null == request.getOptions() || StringUtils.isBlank(request.getStartDate()) || StringUtils.isBlank(request.getEndDate())) {
            // 上报的参数有误
            return ResultDataDto.addOperationFailure(StringOutputConstant.CODE_PARAM_ERROR);
        }

        List<ServicePlanOrderRecord> orderList = null;
        try {
            String fileName = "ORDER_" + new SimpleDateFormat("yyyyMMdd").format(new SimpleDateFormat("yyyy-MM-dd").parse(request.getStartDate())) + "-"
                    + new SimpleDateFormat("yyyyMMdd").format(new SimpleDateFormat("yyyy-MM-dd").parse(request.getEndDate()));

            if (StringUtils.isNotBlank(request.getOptions())) {
                //肯定选了某一项
                orderList = orderMapper.orderExportByOptions(request);

                List<Map<String, Object>> listMaps = ExcelUtil.listConvert(orderList);
                String[] names = ExcelUtil.createTitle(request.getOptions().split(","));
                names = ExcelUtil.listConvertArr(names, "归属企业");
                String[] keys = request.getOptions().split(",");
                keys = ExcelUtil.listConvertArr(keys, "partnerName");
                ExcelUtil.exportExcel2007(response, fileName, names, keys, listMaps);

                return ResultDataDto.addOperationSuccess();
            } else {
                //全部都没有选择
                orderList = orderMapper.orderExportByDefault(request);

                List<Map<String, Object>> listMaps = ExcelUtil.listConvert(orderList);
                String[] names = {"归属企业", "交易编码", "设备编号", "套餐名称", "购买周期", "订单总额", "货币单位",
                        "支付时间", "订单状态", "支付状态", "激活时间"};

                //用这句话来选择key的话，sql语句那边不能写成select *；String[] keys = maps.get(0).entrySet().toArray(new String[maps.get(0).size()]);要写成具体的name对应的字段名，所以这样比较麻烦，我们这边直接指出key，写死就可以了
//                String[] keys = {"partnerName", "payId", "deviceCode", "servicePlanShowName", "orderPeriod", "payAmount", "payCurrency",
//                        "payResultDate", "packageStatus", "payStatus", "orderStartDate"};

                //订单金额字段由payAmount（一个订单号支付的总额）变成payUnit（每张卡付的单价）
                String[] keys = {"partnerName", "payId", "deviceCode", "servicePlanShowName", "orderPeriod", "payUnit", "payCurrency",
                        "payResultDate", "packageStatus", "payStatus", "orderStartDate"};
                ExcelUtil.exportExcel2007(response, fileName, names, keys, listMaps);

                return ResultDataDto.addOperationSuccess();
            }
        } catch (Exception e) {
            log.info("时间格式转换发生异常" + e);
        }
        return null;
    }

    /***
     * 确认退款
     * @param payId
     * @param token
     * @return
     */
    @Override
    public ResultDataDto refund(RequestOrderDetails request, String token) {

        if (StringUtils.isBlank(token)) {
            return ResultDataDto.addOperationFailure(StringOutputConstant.CODE_TOKEN_EMPTY);
        }
        //1,先去公共服务类验证token
        String results = utilsService.checkToken(token);

        if (StringUtils.isBlank(results) || !StringOutputConstant.CODE_SUCCESS.equals(results)) {
            // 验证token出现问题，直接返回
            return ResultDataDto.addOperationFailure(results);
        }
        //确认安全，开始验证参数
        if (StringUtils.isBlank(request.getPartnerCode()) || StringUtils.isBlank(request.getDeviceCode()) || StringUtils.isBlank(request.getPayId()) || StringUtils.isBlank(request.getLang()) || StringUtils.isBlank(request.getVersion()) || StringUtils.isBlank(request.getTradeType())) {
            // 上报的参数有误
            return ResultDataDto.addOperationFailure(StringOutputConstant.CODE_PARAM_ERROR);
        }

        //1，先去将订单表里面的订单致成已退款状态
        ServicePlanOrderRecord order = new ServicePlanOrderRecord();
        order.setDeviceCode(request.getDeviceCode());
        order.setPayId(request.getPayId());
        //套餐支付状态：1-已支付；2-已退款
        order.setPayStatus("2");
        Integer count = orderMapper.refund(order);

        if (count <= 0) {
            return ResultDataDto.addOperationFailure("退款失败，稍后再试！");
        }

        List<ServicePlanOrderRecord> orderList = orderMapper.getOrderByPayId(request.getPayId(), request.getDeviceCode());

        for (ServicePlanOrderRecord o : orderList) {
            // 2，再去生成一条退款记录
            ServicePlanOrderRefund refundOrder = new ServicePlanOrderRefund();
            refundOrder.setPayId(request.getPayId());
            refundOrder.setDeviceCode(o.getDeviceCode());
            refundOrder.setPayAmount(o.getPayUnit());
            refundOrder.setPayCurrency(o.getPayCurrency());
            refundOrder.setPartnerName(o.getPartnerName());
            refundOrder.setPackageName(o.getPackageName());
            refundOrder.setServicePlanShowName(o.getServicePlanShowName());
            orderMapper.writeRefundRecord(refundOrder);
        }
        return ResultDataDto.addOperationSuccess();
    }

    /**
     * 验证请求的date类型是不是合法的时间格式
     *
     * @param date
     * @return
     */
    public static String checkDateFormat(String date, SimpleDateFormat df) {
        df.setLenient(false);
        Date paraDate = null;
        try {
            paraDate = df.parse(date);
        } catch (ParseException e) {
            return "";
        }
        return df.format(paraDate);
    }
}